diff options
Diffstat (limited to 'app/api/basic-contract/[contractId]/sign-source/route.ts')
| -rw-r--r-- | app/api/basic-contract/[contractId]/sign-source/route.ts | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/app/api/basic-contract/[contractId]/sign-source/route.ts b/app/api/basic-contract/[contractId]/sign-source/route.ts new file mode 100644 index 00000000..9f51f47a --- /dev/null +++ b/app/api/basic-contract/[contractId]/sign-source/route.ts @@ -0,0 +1,118 @@ +import { NextRequest, NextResponse } from "next/server"; +import db from "@/db/db"; +import { basicContract, basicContractTemplates } from "@/db/schema"; +import { eq } from "drizzle-orm"; +import { readFile } from "fs/promises"; +import path from "path"; + +// CORS 헤더 (credentials 사용 시 특정 origin 필요) +function getCorsHeaders(request: NextRequest) { + const origin = request.headers.get('origin') || '*'; + return { + 'Access-Control-Allow-Origin': origin === '*' ? '*' : origin, + 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + 'Access-Control-Allow-Credentials': 'true', + }; +} + +export async function OPTIONS(request: NextRequest) { + return NextResponse.json({}, { headers: getCorsHeaders(request) }); +} + +/** + * 계약서 파일을 읽어서 서명 원문으로 사용할 수 있는 형태로 반환 + */ +export async function GET( + request: NextRequest, + { params }: { params: Promise<{ contractId: string }> } +) { + console.log('🔵 [sign-source] API 호출됨:', request.url); + try { + const { contractId: contractIdStr } = await params; + console.log('🔵 [sign-source] contractId:', contractIdStr); + const contractId = parseInt(contractIdStr, 10); + + if (isNaN(contractId)) { + return NextResponse.json( + { success: false, error: "유효하지 않은 계약서 ID입니다." }, + { status: 400, headers: getCorsHeaders(request) } + ); + } + + // 계약서 정보 조회 + const [contract] = await db + .select({ + id: basicContract.id, + filePath: basicContract.filePath, + fileName: basicContract.fileName, + templateId: basicContract.templateId, + templateFilePath: basicContractTemplates.filePath, + templateFileName: basicContractTemplates.fileName, + }) + .from(basicContract) + .leftJoin( + basicContractTemplates, + eq(basicContract.templateId, basicContractTemplates.id) + ) + .where(eq(basicContract.id, contractId)) + .limit(1); + + if (!contract) { + return NextResponse.json( + { success: false, error: "계약서를 찾을 수 없습니다." }, + { status: 404, headers: getCorsHeaders(request) } + ); + } + + // 계약서 파일 경로 결정 (서명된 파일이 있으면 그것을, 없으면 템플릿 파일 사용) + const filePath = contract.filePath || contract.templateFilePath; + const fileName = contract.fileName || contract.templateFileName || "contract.pdf"; + + if (!filePath) { + return NextResponse.json( + { success: false, error: "계약서 파일을 찾을 수 없습니다." }, + { status: 404, headers: getCorsHeaders(request) } + ); + } + + // 파일 읽기 + const nasPath = process.env.NAS_PATH || "/evcp_nas"; + let fullPath: string; + + if (process.env.NODE_ENV === "production") { + fullPath = path.join(nasPath, filePath); + } else { + fullPath = path.join(process.cwd(), "public", filePath); + } + + const fileBuffer = await readFile(fullPath); + + // 파일 내용을 Base64로 인코딩 + const base64Content = fileBuffer.toString("base64"); + + // 서명 원문 형식: <html><title>contract file</title><body>파일내용|파일명</body></html> + const oriMsg = `<html><title>contract file</title><body>${base64Content}|${fileName}</body></html>`; + + return NextResponse.json({ + success: true, + data: { + signSrc: oriMsg, + fileName: fileName, + fileSize: fileBuffer.length, + }, + }, { headers: getCorsHeaders(request) }); + } catch (error) { + console.error("계약서 서명 원문 조회 실패:", error); + return NextResponse.json( + { + success: false, + error: + error instanceof Error + ? error.message + : "계약서 파일을 읽는 중 오류가 발생했습니다.", + }, + { status: 500, headers: getCorsHeaders(request) } + ); + } +} |
